ES7新特性
1.Array.prototype.includes()方法
在 ES6
中我们有 String.prototype.includes()
可以查询给定字符串是否包含一个字符,而在 ES7
中,我们在数组中也可以用 Array.prototype.includes
方法来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回true
,否则返回false
。
const arr = [1, 3, 5, 2, '8', NaN, -0]
arr.includes(1) // true
arr.includes(1, 2) // false 该方法的第二个参数表示搜索的起始位置,默认为0
arr.includes('1') // false
arr.includes(NaN) // true
arr.includes(+0) // true
在ES7之前想判断数组中是否包含一个元素,有如下两种方法, 但都不如includes来得直观:
- indexOf()
indexOf()
方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1
if (arr.indexOf(el) !== -1) {
// ...
}
不过这种方法有两个缺点,一是不够语义化,要先找到参数值的第一个出现位置,所以要去比较是否不等于 - 1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对NaN
的误判。
[NaN].indexOf(NaN)// -1
- find() 和 findIndex()
数组实例的find
方法,用于找出第一个符合条件的数组成员。另外,这两个方法都可以发现NaN
,弥补了数组的indexOf
方法的不足。
[1, 4, -5, 10].find((n) => n < 0) // -5
[1, 5, 10, 15].findIndex(function(value) {
return value > 9;
}) // 2
[NaN].findIndex(y => Object.is(NaN, y)) // 0
2.求幂运算符
在ES7
中引入了指数运算符,具有与Math.pow()
等效的计算结果
console.log(2**10);// 输出1024
console.log(Math.pow(2, 10)) // 输出1024
ES8新特性
1.Async / Await
我们都知道使用Promise
能很好地解决回调地狱的问题,但如果处理流程比较复杂的话,那么整段代码将充斥着then
,语义化不明显,代码不能很好地表示执行流程,那有没有比Promise
更优雅的异步方式呢?
假如有这样一个使用场景:需要先请求a链接,等返回信息之后,再请求b链接的另外一个资源。下面代码展示的是使用fetch
来实现这样的需求,fetch
被定义在window
对象中,它返回的是一个Promise
对象
fetch('https://github.com/Gregory-wyg')
.then(response => {
console.log(response)
return fetch('https://gitee.com/gregory_wu')
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
虽然上述代码可以实现这个需求,但语义化不明显,代码不能很好地表示执行流程。基于这个原因,ES8
引入了async / await
,这是JavaScript
异步编程的一个重大改进,提供了在不阻塞主线程的情况下使用同步代码实现异步访问资源的能力,并且使得代码逻辑更加清晰。
async function foo () {
try {
let response1 = await fetch('https://github.com/Gregory-wyg')
console.log(response1)
let response2 = await fetch('https://gitee.com/gregory_wu')
console.log(response2)
} catch (err) {
console.error(err)
}
}
foo()
通过上面代码,你会发现整个异步处理的逻辑都是使用同步代码的方式来实现的,而且还支持try catch
来捕获异常,这感觉就在写同步代码,所以是非常符合人的线性思维的。需要强调的是, await
不可以脱离 async
单独使用 await
后面一定是Promise
对象,如果不是会自动包装成Promise
对象。
根据MDN定义, async
是一个通过异步执行并隐式返回Promise
作为结果的函数。
async function foo () {
return 'gregory'
}
foo().then(val => {
console.log(val) // gregory
})
上述代码,我们可以看到调用async
声明的foo
函数返回了一个Promise
对象,等价于下面代码:
async function foo () {
return Promise.resolve('gregory')
}
foo().then(val => {
console.log(val) // gregory
})
2.Object.values() ,Object.entries()
ES5
引入了Object.keys
方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。ES8引入了跟Object.keys
配套的Object.values
和Object.entries
,作为遍历一个对象的补充手段,供for...of
循环使用。
Object.values
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值。
const obj = { foo: 'bar', baz: 42 };
Object.values(obj) // ["bar", 42]
const obj = { 100: 'a', 2: 'b', 7: 'c' };
Object.values(obj) // ["b", "c", "a"]
需要注意的是,如果属性名为数值的属性,是按照数值大小,从小到大遍历的,因此返回的顺序是b、c、a。Object.entries()
方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。这个特性我们后面介绍ES10
的Object.fromEntries()
还会再提到。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]
const obj = { 10: 'xxx', 1: 'yyy', 3: 'zzz' };
Object.entries(obj); // [['1', 'yyy'], ['3', 'zzz'], ['10': 'xxx']]
3.String padding
在ES8
中String
新增了两个实例函数 String.prototype.padStart
和 String.prototype.padEnd
,允许将空字符串或其他字符串添加到原始字符串的开头或结尾。我们先看下使用语法:
String.padStart(targetLength,[padString])
targetLength
(必填): 当前字符串需要填充到的目标长度。如果这个数值小于当前字符串的长度,则返回当前字符串本身。padString
(可选): 填充字符串。如果字符串太长,使填充后的字符串长度超过了目标长度,则只保留最左侧的部分,其他部分会被截断,此参数的缺省值为 “ “。
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
有时候我们处理日期、金额的时候经常要格式化,这个特性就派上用场:
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"